--
-- 设置包路径
package.path  = package.path .. ';../?.lua;../lua/?.lua;../lua/src/?.lua';

-- 导入包
require 'math'
require('com.PRINT');
require('com.string');
require('com.table');
require('com.print_r');
require('def.AEvent');
require("cjson")
--~ require('src.OPCODE');
require('src.COMMANDS');
--加载md5模块


-----------------------------
--|
--|		全局变量
--|
-----------------------------

argSocket 		= {}; 		-- socket集合
argUser   		= {}; 		-- user集合
argUserLock   	= {}; 		-- user黑名单
argTeam   		= {}; 		-- team集合

admins          = {}        -- 聊天管理员
sockets         = {}        -- 连接断开时用到
users           = {}        --  所有玩家
blacklist       = {}        --  黑名单玩家
teamlist        = {}        --  所有队伍
channels        = {}        --  所有频道
leagues         = {}        --  仙盟
maps            = {}        --  地图
offlines        = {}        --  离线消息
blackcommands   = {chatworld=1}
systemcommands  = {speeker=1,misson=1,removeblacklist=1,systemusers=1,kickuser=1,addreject=1,delreject=1,shutdown=1,hotrestart=1,addmapuser=1,removemapuser=1}
systemusers     = {root=1,chat_admin=1,['0']=1,dietoad=1,firedtoad=1}
rejectips       = {}        --  禁止IP列表
reloginusers    = {}        --  被顶号列表
camps           = {}        --  阵营
server_status   = 1         --  服务器状态1 为正常开放 0 为关闭 不再接受新玩家登陆

--~ argLobby   		= {}; 		-- 大厅集合


-----------------------------
--|
--|		Lua接口函数
--|
-----------------------------
	-- 初始化
	function OnInit()
		-- 加载配置文件
		require('config');
		-- 调试模式
		if __DEBUG__ then
			_G['_CNetSend'] = _G['CNetSend'];
			_G['CNetSend'] = function(socket,dataEx)
				print('[send:' .. socket ..']',dataEx);
		 		_G['_CNetSend'](socket,dataEx);
			end
		end

		-- 锁住全局表
		setmetatable(_G,{__newindex = LOCK_ADD});
		return 0;
	end

	function InitBlackList(black_users)
		for i,user in pairs(black_users) do
			blacklist[user]=1
		end
		print_r(blacklist)
 		return 0
	end


    function OnCommand(sock,data,ip)
--~ 		 print_r(...)
         local funcs=_G['COMMANDS']
--~ 		   if data['uid']~=nil then data['u']=data['uid'] end
		  if rejectips[ip]~=nil then
			  CNetSend(sock,{c='deny',m='your_ip_was_not_allow'})
			  return 0
		  end

		  if data['c']~=nil and data['c']~='login' and sockets[sock]==nil then
		      CNetSend(sock,{c=data['c'],m='please_login_first'})
			  return 0
		  end
          -- 处理顶号情况
		  if reloginusers[sock]~=nil and reloginusers[sock]==sock then
--~ 			管理员不存在顶号登陆问题
            if users[sockets[sock]]~=nil and systemusers[sockets[sock]]==nil then
			    CNetSend(sock,{c=data['c'],m='be_relogin_please_logout'})
				return 0
			elseif users[sockets[sock]]==nil then
			    reloginusers[sock]=nil
			end
		  end

--~ 		  禁言后不能聊天
		  if sockets[sock]~=nil and blacklist[sockets[sock]]~=nil and data['c']~=nil and blackcommands[data['c']]~=nil then
		      CNetSend(sock,{c='deny',m='you_are_in_black_list'})
			  return 0
		  end

		if data['c'] ~=nil and funcs[data['c']] ~=nil then
		   if systemcommands[data['c']]~=nil and systemusers[sockets[sock]]==nil then
		    data['c']='deny'
			data['m']='not_admin_user'
			return CNetSend(sock,data)
		   end
		   print(sock,data,ip)
		   local func=funcs[data['c']]
		   return func(sock,data,ip)
		end
		CNetSend(sock,{c='unknown',m='no_such_method'})
		return 0
--~ 		 CNetSend(sock,...)
	end

	-- 接收数据
	function OnAEvent(socket,dataEx,ctable)
		-- 运算时间相关(调试模式)
		local startTime;
        print_r(ctable)
        if 1 then return end
		if __DEBUG__ then
			startTime = CGetTime();
			print('[recv:' .. socket ..']'..dataEx);
		end

		 io.write("----this is debug:"..dataEx.."-----\n");

        if string.sub(dataEx,1,3) ==tgwHeader then
		   return 0;
		end
		-- 发送策略文件
		if dataEx == '<policy-file-request/>' then
			CNetSend(socket,'<cross-domain-policy><site-control permitted-cross-domain-policies=\"all\"/><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>');
			PRINT.MSG("!! send policy");
			return 0;
		else

			-- 解析数据
			local arg = dataEx:split(_EN_);
			if #arg > 2 then
				PRINT.ERROR("!! Error package");
				return 1;
			end
			local event = arg[1];
			if not event then
				PRINT.ERROR("!! Unknonw evnet");
				return 1;
			end

			-- 获取入口函数
			local line = _G['OPCODE'];
			local func = line[event];
			if not func then
				io.write("--------------------------------------- error:" .. socket .. ',' .. event .. '\n');
				return 1;
			end

			if arg[2] == nil then
				io.write("--------------------------------------- error:" .. socket .. ',' .. 'no dataEX '.. '\n');
				return 1;
			end

			-- 处理数据
			local err_no = func(socket,arg[2]);
			if __DEBUG__ then
				io.write('--------------------------------------- spend time:' .. (CGetTime() - startTime) .. '\n');
			end
			return err_no;
		end
	end

	-- 连接关闭
	function OnClose_Socket(socket)

		-- 获取用户
		local user = users[sockets[socket]]

		--print(filters[1]);
		if not user then
			PRINT.MSG('unknow user, and socketId is:' .. socket)
		else


			io.write('user '..user['u']..'  close  '..'\n')
            local key=sockets[socket]
			sockets[socket]=nil
		    if user['relogin']~=nil and user['relogin']==true and user['socket_id']~=socket then
                 users[key]['relogin']=nil
				 reloginusers[socket]=nil
				 --print_r(users[sockets[socket]])
				return 0
			end
			users[user['u']]=nil
			if systemusers[user['u']]~=nil then
                 return 0
			end

--~          管理员不在此列

		    if user['teamid']~=0 then
			 	    local team=teamlist[user['teamid']]
				    if type(team)=='table' and next(team)~=nil then
					    for x,y in pairs(team) do
                           if x ~= user['u'] then
							    CNetSend(y['socket_id'],{c='quitteam',user=user['u'],message='quit_team'})
						   end
					    end
						team[user['u']]=nil
						if next(team)==nil then
							teamlist[user['teamid']]=nil
						end
					end
			end
--~         清除地图
			if maps[user['scene_id']]~=nil and maps[user['scene_id']][user['u']] ~=nil then
			--通知地图中的其他人
			    local logout={c='logout',u=user['u'],m='logout'}
			    for x,y in pairs(maps[user['scene_id']]) do
					if user['u']~=y and  users[y]~=nil then
   					    CNetSend(users[y]['socket_id'],logout)
					end
				end
			    maps[user['scene_id']][user['u']]=nil
			end
--~ 			清除黑名单
			if blacklist[user['u']] ~=nil then
 				 blacklist[user['u']]=nil
			end
--~ 			清除军团
            if user['league_id']~=nil and leagues[user['league_id']]~=nil then
				leagues[user['league_id']][user['u']]=nil
			end
			local rid=user['rid']
            if rid~=nil then
		         closeNotify(logoutUrl..rid..'&key='..CMd5(systemKey..rid)..'&x='..user['x']..'&y='..user['y'])
			end
		end
	end


-------------------------------------
--
--		本地运行模式
--
-------------------------------------
if not _G['CNetSend'] then
	-- 发送函数
	_G['CNetSend'] = function(socket,dataEx)
		dataEx = tostring(dataEx);
		local arg = dataEx:split(_EN_);
	end
	-- 关闭函数
	_G['CNetClose'] = function(socket)
		PRINT.MSG('A socket1 was closed,ID is:' .. socket);
	end

	-- 获取时间
	_G['CGetTime'] = function()
		return os.time();
	end
	require('md5');
	_G['CMd5'] = function(str)
		return md5.sumhexa(str);
	end
	-- 全局定义
	_G['__temp__'] = '';
	_G['_CB_'] = '\001';
	_G['_EN_'] = '\003';
	_G['_1_']  = '\022';
	_G['_2_']  = '\030';
	_G['_3_']  = '\031';
	_G['systemKey'] = 'sss';
	_G['filter'] = 'TSL_T';
end

-------------------------------------
--
--		单元测试
--
-------------------------------------

--~ OnInit();
--~ local keyTime = os.date("%Y-%m-%d",os.time());
--~ local key1 = CMd5('lengyanid1' .. systemKey.. keyTime);
--~ local key2 = CMd5('lengyanid2' .. systemKey.. keyTime);
--~ local key3 = CMd5('lengyanid3' .. systemKey.. keyTime);

--~ --user 1 请求策略文件  加入全局，加入群组
--~ OnAEvent(1,'10'.. _EN_ ..key1);
--~ OnAEvent(1,'<policy-file-request/>');
--~ OnAEvent(1,'10'.. _EN_ .. 'lengyanid1' .._2_.. 'lengyan1' .._2_..'1'.._2_..'1'.._2_..'1'.._2_..'0'.._2_..'0'.._2_..'0'.._2_..'0'.._2_..'0'.._1_..key1);
--~ OnAEvent(1,'11'.. _EN_ .. 'Steam_1' .._1_..'aaa');
--~ OnAEvent(1,'12'.. _EN_ .. 'Steam_1' .._1_..'aaa');

--~ --user 2 请求策略文件  加入全局  加入群组
--~ OnAEvent(2,'<policy-file-request/>');
--~ OnAEvent(2,'10'.. _EN_ .. 'lengyanid2' .._2_.. 'lengyan2' .._2_..'1'.._2_..'1'.._2_..'1'.._2_..'0'.._2_..'0'.._2_..'0'.._2_..'0'.._2_..'0'.._1_..key2);
--~ OnAEvent(3,'10'.. _EN_ .. 'lengyanid3' .._2_.. 'lengyan3' .._2_..'1'.._2_..'1'.._2_..'1'.._2_..'0'.._2_..'0'.._2_..'0'.._2_..'0'.._2_..'0'.._1_..key3);

--~ OnAEvent(2,'11'.. _EN_ .. 'Steam_1' .._1_..'aaa');
--~ OnAEvent(2,'11'.. _EN_ .. 'Steam_2' .._1_..'aaa');
--~ OnAEvent(2,'11'.. _EN_ .. 'Steam_3' .._1_..'aaa');
--~ OnAEvent(2,'11'.. _EN_ .. 'Steam_4' .._1_..'aaa');
--~ --user 2 退出群组
--~ OnAEvent(2,'12'.. _EN_ .. 'Steam_1' .._1_..'aaa');

--~ OnAEvent(1,'11'.. _EN_ .. 'T_001' .._1_..'aaa');
--~ OnAEvent(2,'11'.. _EN_ .. 'T_001' .._1_..'aaa');
--~ OnAEvent(2,'11'.. _EN_ .. 'T_002' .._1_..'aaa');

--~ OnAEvent(2,'12'.. _EN_ .. 'T_002' .._1_..'aaa');

--~ --广播全局消息
--~ OnAEvent(1,'21'.. _EN_ .. 'aaa');

--~ --广播全局消息
--~ OnAEvent(2,'21'.. _EN_ .. 'aaassss');
--~ OnAEvent(2,'21'.. _EN_ .. 'aaasss1s');
--~ OnAEvent(2,'21'.. _EN_ .. 'aaasss1s');

--~ OnAEvent(1,'52'.. _EN_ .. 'sss'.._1_..'Stea222m_2'.._1_..'8'.._1_..'ssss');

--~ OnAEvent(1,'51'.. _EN_ .. 'sss'.._1_..'Stea222m_2'.._1_..'sss'.._1_..'Stea222m_2');

--~ --发送群组消息
--~ OnAEvent(1,'22'.. _EN_ .. 'Steam_1' .._1_..'aaa');
--~ --发送不存在的群组消息
--~ OnAEvent(2,'22'.. _EN_ .. 'Steam_9' .._1_..'aaa');


--~ --lengyan_1发送给lengyan_2  附带抄送
--~ OnAEvent(1,'24'.. _EN_ .. 'lengyan2' .._1_..'aaa');

--~ --lengyan_1发送给lengyan_2  不抄送
--~ OnAEvent(1,'25'.. _EN_ .. 'lengyan2' .._1_..'aaa');

--~ --lengyan_1发送给lengyan_3  不抄送
--~ OnAEvent(1,'25'.. _EN_ .. 'lengyan3' .._1_..'aaa');

--~ --获取lengyan_1信息
--~ OnAEvent(1,'30'.. _EN_ .. 'lengyan2');

--~ --获取team_1列表
--~ OnAEvent(1,'31'.. _EN_ .. 'Steam_1');


--~ OnAEvent(1,'61'.. _EN_ .. 'sss');

--~ OnAEvent(1,'88'.. _EN_ .. 'sss' .._1_.. 'lengyan2');

--~ --广播全局消息
--~ OnAEvent(2,'21'.. _EN_ .. 'aaa');



